package com.easybbs.controller;

import com.easybbs.annotation.Globallnterceptor;
import com.easybbs.annotation.VerifyParam;
import com.easybbs.entity.config.WebConfig;
import com.easybbs.entity.constants.Constants;
import com.easybbs.entity.dto.SessionWebUserDto;
import com.easybbs.entity.enums.*;
import com.easybbs.entity.po.*;
import com.easybbs.entity.query.ForumArticleAttachmentQuery;
import com.easybbs.entity.query.ForumArticleQuery;
import com.easybbs.entity.vo.PaginationResultVO;
import com.easybbs.entity.vo.ResponseVO;
import com.easybbs.entity.vo.web.FormArticleDetailVO;
import com.easybbs.entity.vo.web.ForumArticleAttachmentVo;
import com.easybbs.entity.vo.web.ForumArticleVO;
import com.easybbs.entity.vo.web.UserDownloadInfoVO;
import com.easybbs.exception.BusinessException;
import com.easybbs.service.*;
import com.easybbs.utils.CopyTools;
import com.easybbs.utils.StringTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.Mapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.URLEncoder;
import java.util.List;

@RestController
@RequestMapping("/forum")
public class ForumArticleController extends BaseController {
    private static final Logger logger = LoggerFactory.getLogger(ForumArticleController.class);
    @Autowired
    private ForumArticleService articleService;

    @Autowired
    private ForumArticleAttachmentService forumArticleAttachmentService;

    @Autowired
    private LikeRecordService likeRecordService;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private ForumArticleAttachmentDownloadService forumArticleAttachmentDownloadService;

    @Autowired
    private WebConfig webConfig;

    @Autowired
    private ForumBoardService forumBoardService;


    /**
     * 获取文章列表
     *
     * @param session
     * @param boardId
     * @param pBoardId
     * @param orderType
     * @param pageNo
     * @return
     */
    @RequestMapping("/loadArticle")
    public ResponseVO loadArticle(HttpSession session, Integer boardId, Integer pBoardId, Integer orderType, Integer pageNo) {
        ForumArticleQuery articleQuery = new ForumArticleQuery();
        articleQuery.setBoardId(boardId == null || boardId == 0 ? null : boardId);
        articleQuery.setpBoardId(pBoardId);
        articleQuery.setPageNo(pageNo);

        //获取存在session中的登录信息
        SessionWebUserDto userDto = getUserInfoFromSession(session);
        //进行判断是否有登录信息
        if (userDto != null) {
            //过滤文章信息（只要已审核的）
            articleQuery.setCurrentUserId(userDto.getUserId());
        } else {
            articleQuery.setStatus(ArticleStatusEnum.AUDIT.getStatus());
        }
        //根据类型进行排序
        ArticleOrderTypeEnum orderTypeEnum = ArticleOrderTypeEnum.getByType(orderType);
        orderTypeEnum = orderTypeEnum == null ? ArticleOrderTypeEnum.HOT : orderTypeEnum;
        articleQuery.setOrderBy(orderTypeEnum.getOrderSql());
        PaginationResultVO resultVO = articleService.findListByPage(articleQuery);
        //使用convert2PaginationVO方法将一些不要的数据清除
        return getSuccessResponseVO(convert2PaginationVO(resultVO, ForumArticleVO.class));
    }

    /**
     * 获取文章详情 (会更新阅读数、点赞、评论数)
     *
     * @param session
     * @param articleId
     * @return
     */
    @RequestMapping("/getArticleDetail")
    @Globallnterceptor(checkParams = true)
    public ResponseVO getArticleDetail(HttpSession session, @VerifyParam(required = true) String articleId) {
        //拿到用户登录信息
        SessionWebUserDto sessionWebUserDto = getUserInfoFromSession(session);

        ForumArticle forumArticle = articleService.readArticle(articleId);
        //判断是否显示文章的条件
        //Boolean canShowNoAudit = sessionWebUserDto != null && sessionWebUserDto.getUserId().equals(forumArticle.getUserId()) || sessionWebUserDto.getAdmin();
        if (forumArticle == null
                || (ArticleStatusEnum.NO_AUDIT.getStatus().equals(forumArticle.getStatus()) && (sessionWebUserDto == null || !sessionWebUserDto.getUserId().equals(forumArticle.getUserId()) && !sessionWebUserDto.getAdmin()))
                || ArticleStatusEnum.DEL.getStatus().equals(forumArticle.getStatus())) {
            throw new BusinessException(ResponseCodeEnum.CODE_404);
        }
        //存储文章详情的对象
        FormArticleDetailVO detailVO = new FormArticleDetailVO();
        //将不同类型的对象进行拷贝 forumArticle是（ForumArticle对象） detailVO是（FormArticleDetailVO对象）
        detailVO.setForumArticle(CopyTools.copy(forumArticle, ForumArticleVO.class));

        //判断有附件 0是有 1是没有
        if (forumArticle.getAttachmentType() == Constants.ONE) {
            ForumArticleAttachmentQuery articleAttachmentQuery = new ForumArticleAttachmentQuery();
            //使用的是我们查询到文章的id 而不是传递过来的id
            articleAttachmentQuery.setArticleId(forumArticle.getArticleId());
            //查询多个附件
            List<ForumArticleAttachment> forumArticleAttachmentList = forumArticleAttachmentService.findListByParam(articleAttachmentQuery);
            if (!forumArticleAttachmentList.isEmpty()) {
                //TODO 这里只取了第一个附件 我们可以取多个自己可以改造
                detailVO.setAttachment(CopyTools.copy(forumArticleAttachmentList.get(0), ForumArticleAttachmentVo.class));
            }
        }

        //判断当前用户已经登录
        if (sessionWebUserDto != null) {
            //查询点赞的数据
            LikeRecord likeRecord = likeRecordService.getUserOperRecordByObjectIdAndUserIdAndOpType(articleId, sessionWebUserDto.getUserId(), OperRecordOpTypeEnum.ARTICLE_LIKE.getType());
            //已经点赞
            if (likeRecord != null) {
                //返回并设置展示页面点赞的数据
                detailVO.setHaveLike(true);
            }
        }
        return getSuccessResponseVO(detailVO);
    }

    /**
     * 文章点赞功能
     *
     * @param session
     * @param articleId
     * @return
     */
    @RequestMapping("/doLike")
    @Globallnterceptor(checkParams = true, checkLogin = true, frequencyType = UserOperFrequencyTypeEnum.DO_LIKE)
    //是否需要传参 是否需要登录
    public ResponseVO doLike(HttpSession session, @VerifyParam(required = true) String articleId) {
        //获取到了登录用户信息
        SessionWebUserDto sessionWebUserDto = getUserInfoFromSession(session);
        likeRecordService.doLike(articleId, sessionWebUserDto.getUserId(), sessionWebUserDto.getNickName(), OperRecordOpTypeEnum.ARTICLE_LIKE);
        return getSuccessResponseVO(null);
    }

    /**
     * 获取用户的下载附件信息(是否下载过、积分)
     *
     * @param session
     * @param fileId
     * @return
     */
    @RequestMapping("/getUserDownloadInfo")
    @Globallnterceptor(checkParams = true, checkLogin = true) //是否需要传参 是否需要登录
    public ResponseVO getUserDownloadInfo(HttpSession session, @VerifyParam(required = true) String fileId) {
        SessionWebUserDto sessionWebUserDto = getUserInfoFromSession(session);
        //查询用户信息的用户积分是否够
        UserInfo userInfo = userInfoService.getUserInfoByUserId(sessionWebUserDto.getUserId());
        UserDownloadInfoVO downloadInfoVO = new UserDownloadInfoVO();
        downloadInfoVO.setUserIntegral(userInfo.getCurrentIntegral()); //获取用户当前的积分 不是总积分
        //查询用户是否已经下载过附件数据
        ForumArticleAttachmentDownload attachmentDownload = forumArticleAttachmentDownloadService.getForumArticleAttachmentDownloadByFileIdAndUserId(fileId,
                sessionWebUserDto.getUserId());

        if (attachmentDownload != null) {
            //用户下载过
            downloadInfoVO.setHaveDownload(true);
        }

        //返回的应该是查询过的下载附件数据
        return getSuccessResponseVO(downloadInfoVO);
    }

    /**
     * 下载附件文件
     *
     * @param session
     * @param request
     * @param response
     * @param fileId
     */
    @RequestMapping("/attachmentDownload")
    @Globallnterceptor(checkLogin = true, checkParams = true)
    public void attachmentDownload(HttpSession session, HttpServletRequest request, HttpServletResponse response,
                                   @VerifyParam(required = true) String fileId) {
        ForumArticleAttachment attachment = forumArticleAttachmentService.downloadAttachment(fileId, getUserInfoFromSession(session));
        InputStream in = null;
        OutputStream out = null;
        //下载文件名
        String downloadFileName = attachment.getFileName();
        //文件路径
        String filePath = webConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE + Constants.FILE_FOLDER_ATTACHMENT + attachment.getFilePath();
        File file = new File(filePath);
        try {
            in = new FileInputStream(file);
            out = response.getOutputStream();
            response.setContentType("application/x-msdownload; charset=UTF-8");
            // 解决中文文件名乱码问题
            if (request.getHeader("User-Agent").toLowerCase().indexOf("msie") > 0) {//IE浏览器
                downloadFileName = URLEncoder.encode(downloadFileName, "UTF-8");
            } else {
                downloadFileName = new String(downloadFileName.getBytes("UTF-8"), "ISO8859-1");
            }
            response.setHeader("Content-Disposition", "attachment;filename=\"" + downloadFileName + "\"");
            byte[] byteData = new byte[1024];
            int len = 0;
            while ((len = in.read(byteData)) != -1) {
                out.write(byteData, 0, len); // write
            }
            out.flush();
        } catch (Exception e) {
            logger.error("下载异常", e);
            throw new BusinessException("下载失败");
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                logger.error("IO异常", e);
            }
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                logger.error("IO异常", e);
            }
        }
    }

    /**
     * 发布文章 - 获取模板板块分类 举例：(前端、后端)
     *
     * @param session
     * @return
     */
    @RequestMapping("/loadBoard4Post")
    @Globallnterceptor(checkLogin = true)
    public ResponseVO loadBoard4Post(HttpSession session) {
        //通过session获取用户信息进行判断是否为管理员
        SessionWebUserDto sessionWebUserDto = getUserInfoFromSession(session);
        Integer postType = null;
        if (!sessionWebUserDto.getAdmin()) {
            postType = Constants.ONE;
        }
        //返回查询的模板数据
        return getSuccessResponseVO(forumBoardService.getBoardTree(postType));
    }

    /**
     * 发布文章
     *
     * @param session
     * @param cover           封面
     * @param attachment      附件
     * @param integral        积分
     * @param title           标题
     * @param pBoardId        父模板id
     * @param boardId         模板id
     * @param summary         摘要
     * @param editorType      编辑器类型
     * @param content         内容
     * @param markdownContent mrkdown内容
     * @return
     */
    @RequestMapping("/postArticle")
    @Globallnterceptor(checkLogin = true, checkParams = true, frequencyType = UserOperFrequencyTypeEnum.POST_ARTICLE)
    public ResponseVO postArticle(HttpSession session,
                                  MultipartFile cover,
                                  MultipartFile attachment,
                                  Integer integral,
                                  @VerifyParam(required = true, max = 150) String title,
                                  @VerifyParam(required = true) Integer pBoardId,
                                  Integer boardId,
                                  @VerifyParam(max = 200) String summary,
                                  @VerifyParam(required = true) Integer editorType,
                                  @VerifyParam(required = true) String content,
                                  String markdownContent) {
        title = StringTools.escapeHTML(title);
        SessionWebUserDto webUserDto = getUserInfoFromSession(session);

        ForumArticle forumArticle = new ForumArticle();
        forumArticle.setpBoardId(pBoardId);
        forumArticle.setBoardId(boardId);
        forumArticle.setTitle(title);
        forumArticle.setContent(content);

        EditorTypeEnum typeEnum = EditorTypeEnum.getByType(editorType);
        if (typeEnum == null) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }

        //判断是否是markdown编辑器
        if (EditorTypeEnum.MARKDOWN.getType().equals(editorType) && StringTools.isEmpty(markdownContent)) {
            throw new BusinessException("markdown内容不能为空");
        }
        forumArticle.setMarkdownContent(markdownContent);
        forumArticle.setEditorType(editorType);
        forumArticle.setUserId(webUserDto.getUserId());
        forumArticle.setNickName(webUserDto.getNickName());
        forumArticle.setUserIpAddress(webUserDto.getProvince());
        forumArticle.setSummary(summary);

        //附件信息
        ForumArticleAttachment forumArticleAttachment = new ForumArticleAttachment();
        forumArticleAttachment.setIntegral(integral == null ? 0 : integral);

        //发布文章
        articleService.postArticle(webUserDto.getAdmin(), forumArticle, forumArticleAttachment, cover, attachment);
        return getSuccessResponseVO(forumArticle.getArticleId());
    }

    /**
     * 修改文章
     *
     * @param session
     * @param articleId
     * @return
     */
    @RequestMapping("/articleDetail4Update")
    @Globallnterceptor(checkLogin = true, checkParams = true)
    public ResponseVO articleDetail4Update(HttpSession session, @VerifyParam(required = true) String articleId) {
        SessionWebUserDto userDto = getUserInfoFromSession(session);
        ForumArticle forumArticle = articleService.getForumArticleByArticleId(articleId);
        //文章不存在 发布人和当前登录人不一致 无法修改
        if (forumArticle == null || !forumArticle.getUserId().equals(userDto.getUserId())) {
            throw new BusinessException("文章不存在或没有权限修改");
        }
        FormArticleDetailVO detailVO = new FormArticleDetailVO();
        detailVO.setForumArticle(CopyTools.copy(forumArticle, ForumArticleVO.class));

        //判断是否有附件
        if (forumArticle.getAttachmentType() == Constants.ONE) {
            ForumArticleAttachmentQuery articleAttachmentQuery = new ForumArticleAttachmentQuery();
            articleAttachmentQuery.setArticleId(articleId);
            //查询多个附件
            List<ForumArticleAttachment> forumArticleAttachmentList = forumArticleAttachmentService.findListByParam(articleAttachmentQuery);
            if (!forumArticleAttachmentList.isEmpty()) {
                //TODO 这里只取了第一个附件 我们可以取多个自己可以改造
                detailVO.setAttachment(CopyTools.copy(forumArticleAttachmentList.get(0), ForumArticleAttachmentVo.class));
            }
        }
        return getSuccessResponseVO(detailVO);
    }

    /**
     * 更新文章
     *
     * @param session
     * @param cover
     * @param attachment
     * @param integral
     * @param articleId
     * @param title
     * @param pBoardId
     * @param boardId
     * @param summary
     * @param editorType
     * @param content
     * @param markdownContent
     * @param attachmentType
     * @return
     */
    @RequestMapping("/updateArticle")
    @Globallnterceptor(checkLogin = true, checkParams = true)
    public ResponseVO updateArticle(HttpSession session,
                                    MultipartFile cover,
                                    MultipartFile attachment,
                                    Integer integral,
                                    @VerifyParam(required = true) String articleId,
                                    @VerifyParam(required = true, max = 150) String title,
                                    @VerifyParam(required = true) Integer pBoardId,
                                    Integer boardId,
                                    @VerifyParam(max = 200) String summary,
                                    @VerifyParam(required = true) Integer editorType,
                                    @VerifyParam(required = true) String content,
                                    String markdownContent,
                                    @VerifyParam Integer attachmentType) {
        title = StringTools.escapeHTML(title);
        SessionWebUserDto userDto = getUserInfoFromSession(session);
        ForumArticle forumArticle = new ForumArticle();
        forumArticle.setArticleId(articleId);
        forumArticle.setpBoardId(pBoardId);
        forumArticle.setBoardId(boardId);
        forumArticle.setTitle(title);
        forumArticle.setContent(content);
        forumArticle.setMarkdownContent(markdownContent);
        forumArticle.setEditorType(editorType);
        forumArticle.setSummary(summary);
        forumArticle.setUserIpAddress(userDto.getProvince());
        forumArticle.setAttachmentType(attachmentType);
        forumArticle.setUserId(userDto.getUserId());
        //附件信息
        ForumArticleAttachment forumArticleAttachment = new ForumArticleAttachment();
        forumArticleAttachment.setIntegral(integral == null ? 0 : integral);
        //更新文章
        articleService.updateArticle(userDto.getAdmin(), forumArticle, forumArticleAttachment, cover, attachment);
        return getSuccessResponseVO(forumArticle.getArticleId());
    }

    /**
     * 搜索文章
     *
     * @param keyword
     * @return
     */
    @RequestMapping("/search")
    @Globallnterceptor(checkParams = true)
    public ResponseVO search(@VerifyParam(required = true, min = 3) String keyword) {
        ForumArticleQuery query = new ForumArticleQuery();
        query.setTitleFuzzy(keyword);
        PaginationResultVO resultVO = articleService.findListByPage(query);
        return getSuccessResponseVO(resultVO);
    }
}
